import json
import os
from django.http import JsonResponse, HttpResponse
from django.shortcuts import render, redirect
from django.contrib import messages
from django.views.decorators.csrf import csrf_exempt
from openpyxl import load_workbook
from openpyxl.drawing.image import Image as ExcelImage
from PIL import Image
from PM.models import ReportData, User
from django.core.paginator import Paginator
from datetime import datetime, timedelta
from django.db.models.functions import TruncMonth
from django.db.models import Count

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# 在模块加载时读取配置文件
config_path = os.path.join(BASE_DIR, 'config.json')
with open(config_path, 'r') as config_file:
    config = json.load(config_file)
    DEPARTMENTS = [(dept, dept) for dept in config.get('DEPARTMENTS', [])]


def index(request):
    engineers = User.objects.all()
    departments = User.objects.values_list('department', flat=True).distinct().exclude(department__isnull=True)

    # Overall Stats
    total_reports = ReportData.objects.count()
    total_engineers = engineers.count()

    # Department Chart Data
    department_chart_data = {
        'names': list(departments),
        'report_counts': [ReportData.objects.filter(department=dept).count() for dept in departments],
        'engineer_counts': [User.objects.filter(department=dept).count() for dept in departments]
    }

    # Monthly Report Trend Data (last 12 months)
    today = datetime.today()
    twelve_months_ago = today - timedelta(days=365)
    monthly_counts = ReportData.objects.filter(report_date__gte=twelve_months_ago) \
        .annotate(month=TruncMonth('report_date')) \
        .values('month') \
        .annotate(count=Count('id')) \
        .order_by('month')

    # Prepare data for the chart
    monthly_report_trend = {'labels': [], 'data': []}
    # Create a dictionary for quick lookups
    counts_dict = {item['month'].strftime('%Y-%m'): item['count'] for item in monthly_counts}
    
    for i in range(12, -1, -1):
        month_date = today - timedelta(days=i * 30)
        month_key = month_date.strftime('%Y-%m')
        if month_key not in monthly_report_trend['labels']:
             monthly_report_trend['labels'].append(month_key)
             monthly_report_trend['data'].append(counts_dict.get(month_key, 0))


    # Engineer Table Data
    engineer_data_table = []
    for engineer in engineers:
        report_count = ReportData.objects.filter(created_by=engineer).count()
        engineer_data_table.append({
            'name': engineer.username,
            'department': engineer.department or 'N/A',
            'reports': report_count,
            'certificates': report_count  # 假设证书数量与报告数量相同
        })
    engineer_data_table.sort(key=lambda x: x['reports'], reverse=True)
    
    # Top 20 Engineers by Certificates
    top_20_engineers = sorted(engineer_data_table, key=lambda x: x['certificates'], reverse=True)[:20]

    context = {
        'current_user': request.current_user,
        'total_reports': total_reports,
        'total_engineers': total_engineers,
        'department_chart_data': json.dumps(department_chart_data),
        'monthly_report_trend': json.dumps(monthly_report_trend),
        'engineer_data_table': engineer_data_table,
        'top_20_engineers': json.dumps(top_20_engineers),
    }
    return render(request, 'index.html', context)


@csrf_exempt
def select_department(request):
    if request.method == 'POST':
        # 获取用户选择的部门并存入 session
        department = request.POST['department']
        request.session['selected_department'] = department  # 将部门信息存入session
        return redirect('generate_report')
    # 获取所有部门列表
    departments = list(config['DEPARTMENTS'].keys())
    return render(request, 'select_department.html', {'departments': departments, 'current_user': request.current_user})


def save_images(images, folder, customer_name, instrument_serial, report_date):
    image_paths = []
    for i, image in enumerate(images):
        img = Image.open(image)
        img.thumbnail((800, 800))
        file_name = f"{customer_name}_{instrument_serial}_{report_date}_{i + 1}.jpg"
        file_path = os.path.join(folder, file_name)
        if img.mode == 'RGBA':
            img = img.convert('RGB')
        img.save(file_path, "JPEG", quality=95)
        image_paths.append(file_path)
    return image_paths


@csrf_exempt
def generate_report(request):
    selected_department = request.session.get('selected_department', None)
    instrument_models = list(config['DEPARTMENTS'][selected_department].keys())
    if request.method == 'POST':
        form_data = request.POST.dict()
        report_date = form_data.get('report_date')
        customer_name = form_data.get('customer_name')
        instrument_serial = form_data.get('instrument_serial')
        before_clean_images = request.FILES.getlist('before_clean_images')
        after_clean_images = request.FILES.getlist('after_clean_images')
        user_folder = os.path.join('PM', 'uploads', request.current_user['username'])
        before_clean_folder = os.path.join(user_folder, 'before_clean')
        after_clean_folder = os.path.join(user_folder, 'after_clean')
        os.makedirs(before_clean_folder, exist_ok=True)
        os.makedirs(after_clean_folder, exist_ok=True)
        before_clean_image_paths = save_images(before_clean_images, before_clean_folder, customer_name,
                                               instrument_serial, report_date)
        after_clean_image_paths = save_images(after_clean_images, after_clean_folder, customer_name, instrument_serial,
                                              report_date)
        user_instance = User.objects.get(username=request.current_user['username'])
        report_data = ReportData(
            data=form_data,
            before_clean_images=','.join(before_clean_image_paths),
            after_clean_images=','.join(after_clean_image_paths),
            report_date=report_date,
            department=selected_department,
            created_by=user_instance
        )
        report_data.save()
        return redirect('report_list')
    return render(request, 'generate_report.html',
                  {'current_user': request.current_user, 'instrument_models': instrument_models})


@csrf_exempt
def load_template(request):
    # 获取用户选择的仪器型号
    instrument_model = request.POST['instrument_model']
    department = request.session.get('selected_department')
    if not instrument_model or not department:
        return JsonResponse({'error': 'Instrument model or department not provided'}), 400
    # 构建模板文件路径
    template_path = os.path.join(BASE_DIR, 'templates', 'html_templates', f"{department}_{instrument_model}.html")
    # 检查模板文件是否存在
    if not os.path.exists(template_path):
        return JsonResponse({'error': 'Template file not found'}), 404

    # 读取并返回模板文件内容
    with open(template_path, 'r', encoding='utf-8') as template_file:
        template_content = template_file.read()

    return JsonResponse({'template': template_content})


@csrf_exempt
def get_report_data(reports):
    report_data_list = []
    for report in reports:
        data = report.data
        report_data = {
            'id': report.id,
            'customer_name': data.get('customer_name', ''),
            'department': report.department,
            'instrument_name': data.get('instrument_name', ''),
            'instrument_model': data.get('instrument_model', ''),
            'instrument_serial': data.get('instrument_serial', ''),
            'report_date': report.report_date.strftime('%Y-%m-%d'),
        }
        report_data_list.append(report_data)
    return report_data_list


@csrf_exempt
def report_list(request):
    current_user = request.current_user
    reports = ReportData.objects.filter(created_by__username=current_user['username']).order_by('-id')
    paginator = Paginator(reports, 20)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    report_data_list = get_report_data(page_obj)
    return render(request, 'report_list.html',
                  {'reports': report_data_list, 'page_obj': page_obj, 'current_user': request.current_user})


@csrf_exempt
def all_report_list(request):
    reports = ReportData.objects.all().order_by('-id')
    paginator = Paginator(reports, 15)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    report_data_list = get_report_data(page_obj)
    return render(request, 'all_report_list.html',
                  {'reports': report_data_list, 'page_obj': page_obj, 'current_user': request.current_user})


@csrf_exempt
def download_report(request, report_id):
    report = ReportData.objects.get(id=report_id)
    department = report.department
    instrument_model = report.data.get('instrument_model')
    template_name = config['DEPARTMENTS'][department][instrument_model]['template']
    fields_mapping = config['DEPARTMENTS'][department][instrument_model]['fields']
    image_positions = config['DEPARTMENTS'][department][instrument_model]['IMAGE_POSITIONS']
    signature_position = config['DEPARTMENTS'][department][instrument_model].get('SIGNATURE')
    template_path = os.path.join(BASE_DIR, 'templates', 'excel_templates', template_name)
    wb = load_workbook(template_path)
    ws = wb.active
    for field, cell in fields_mapping.items():
        ws[cell] = report.data.get(field, '')

    before_clean_images = report.before_clean_images.split(',')

    # 修改：直接split字符串，不访问name属性

    for i, image_path in enumerate(before_clean_images):
        try:
            if os.path.exists(image_path):
                img = ExcelImage(image_path)
                img.width = 330
                img.height = 240
                position = image_positions['before_clean'][i]
                ws.add_image(img, position)
        except Exception as e:
            print(f"Error inserting before clean image: {e}")

    after_clean_images = report.after_clean_images.split(',')
    # 修改：直接split字符串，不访问name属性

    for i, image_path in enumerate(after_clean_images):
        try:
            if os.path.exists(image_path):
                img = ExcelImage(image_path)
                img.width = 330
                img.height = 240
                position = image_positions['after_clean'][i]
                ws.add_image(img, position)
        except Exception as e:
            print(f"Error inserting after clean image: {e}")
    if signature_position:
        signature_path = os.path.join(BASE_DIR, 'static', 'signature', f"{request.current_user['engineer_id']}.png")
        try:
            if os.path.exists(signature_path):
                signature_img = ExcelImage(signature_path)
                signature_img.width = 70
                signature_img.height = 30
                ws.add_image(signature_img, signature_position)
        except Exception as e:
            print(f"Error inserting signature image: {e}")
    response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
    filename = f"{report.data.get('customer_name', 'report')}_{report.data.get('instrument_name', '')}_{report.data.get('instrument_serial', '')}_{report.report_date.strftime('%Y%m%d')}.xlsx"
    # 使用 urllib.parse.quote 对文件名进行编码
    from urllib.parse import quote
    encoded_filename = quote(filename)
    response['Content-Disposition'] = f'attachment; filename*=UTF-8\'\'{encoded_filename}'
    wb.save(response)
    return response


@csrf_exempt
def delete_report(request, report_id):
    report = ReportData.objects.get(id=report_id)
    report.delete()
    return redirect('all_report_list')


@csrf_exempt
def edit_config(request):
    # 读取 config.json 文件内容
    config_path = os.path.join(BASE_DIR, 'config.json')
    with open(config_path, 'r', encoding='utf-8') as config_file:
        config_content = config_file.read()

    if request.method == 'POST':
        # 处理HTML模板上传
        if 'upload_html' in request.POST:
            html_template = request.FILES.get('html_template')
            if html_template:
                # 保存HTML模板到html_templates目录
                html_template_path = os.path.join(BASE_DIR, 'templates', 'html_templates', html_template.name)
                with open(html_template_path, 'wb+') as destination:
                    for chunk in html_template.chunks():
                        destination.write(chunk)
                messages.success(request, 'HTML模板上传成功！')
            else:
                messages.error(request, '请选择HTML模板文件！')

        # 处理Excel模板上传
        elif 'upload_excel' in request.POST:
            excel_template = request.FILES.get('excel_template')
            if excel_template:
                # 保存Excel模板到excel_templates目录
                excel_template_path = os.path.join(BASE_DIR, 'templates', 'excel_templates', excel_template.name)
                with open(excel_template_path, 'wb+') as destination:
                    for chunk in excel_template.chunks():
                        destination.write(chunk)
                messages.success(request, 'Excel模板上传成功！')
            else:
                messages.error(request, '请选择Excel模板文件！')

        # 处理配置内容保存
        elif 'config_content' in request.POST:
            new_config_content = request.POST.get('config_content', '')
            try:
                # 去除所有多余空行并格式化JSON
                parsed_json = json.loads(new_config_content)
                new_config_content = json.dumps(parsed_json, indent=2, ensure_ascii=False)

                # 验证 JSON 格式是否正确
                new_config = json.loads(new_config_content)

                # 保存新的配置内容到 config.json 文件
                with open(config_path, 'w', encoding='utf-8') as config_file:
                    config_file.write(new_config_content)

                # 更新内存中的配置
                global config, DEPARTMENTS
                config = new_config
                DEPARTMENTS = [(dept, dept) for dept in config.get('DEPARTMENTS', [])]

                messages.success(request, '配置文件保存成功！配置已热加载，无需重启系统。')
            except json.JSONDecodeError:
                messages.error(request, '配置文件格式错误，请检查 JSON 格式！')

        return redirect('edit_config')

    # 添加GET请求处理
    return render(request, 'edit_config.html', {
        'config_content': config_content,
        'current_user': request.current_user
    })


@csrf_exempt
def reload_config(request):
    if request.method == 'POST':
        try:
            # 重新加载配置文件
            config_path = os.path.join(BASE_DIR, 'config.json')
            with open(config_path, 'r') as config_file:
                global config, DEPARTMENTS
                config = json.load(config_file)
                DEPARTMENTS = [(dept, dept) for dept in config.get('DEPARTMENTS', [])]

            messages.success(request, '配置热加载成功！')
        except Exception as e:
            messages.error(request, f'配置热加载失败: {str(e)}')
        return redirect('edit_config')
